const dayjs = require('dayjs')
const {
  Service,
} = require('uni-cloud-router')

const {
  TaskStatus,
  PointsAction,
  TaskType,
} = require('../constants/const')

const {
  getCurrentWeek,
  getDate,
} = require('../utils/Date')

const ResponseUtil = require('../utils/Response')

module.exports = class TaskService extends Service {
  async today(data) {
    const { openId, childId } = data

    const db = this.db
    const dbCmd = db.command

    // 获取当前周的开始和结束时间
    const {
      startOfWeek,
      endOfWeek,
    } = getCurrentWeek()

    // 1. 获取所有有效的孩子
    const childrenRes = await db.collection('child').doc(childId).get()

    if (childrenRes.data.length === 0) {
      return ResponseUtil.error('未找到该孩子')
    }

    // 2. 获取家长配置的模版
    let templates = await db.collection('task_templates').where({
      createdBy: openId,
    }).get()

    // 用户模版中的日任务
    const hasDailyTask = templates.data.some(item => item.type === TaskType.Day)
    // 用户模版中的周任务
    const hasWeeklyTask = templates.data.some(item => item.type === TaskType.Week)

    const systemTemplates = await db.collection('task_system_templates').get()
    const systemDailyTask = systemTemplates.data.filter(item => item.type === TaskType.Day)
    const systemWeeklyTask = systemTemplates.data.filter(item => item.type === TaskType.Week)

    // 如果没有配置，就用系统的
    if (!hasDailyTask) {
      templates.data.push(...systemDailyTask)
    }

    if (!hasWeeklyTask) {
      templates.data.push(...systemWeeklyTask)
    }

    // 获取本周内的所有周任务
    const res = await db.collection('daily_task_records')
      .where({
        childId,
        recordDate: dbCmd.and(
          dbCmd.gte(startOfWeek),
          dbCmd.lte(endOfWeek),
        ),
      })
      .get()

    // 本周内已经完成的周任务id
    const weekComplateSet = new Set()
    res.data.map((item) => {
      item.tasks.map((item) => {
        if (item.taskType === 0 && item.status === TaskStatus.Complete) {
          weekComplateSet.add(item.taskId)
        }
        return item
      })
      return item
    })

    const tasks = []
    templates.data.map((item) => {
      // 对当前子女生效的任务
      if (item.isSystem || (item.children && item.children.includes(childId))) {
        tasks.push({
          taskId: item._id,
          taskTitle: item.title,
          taskDescription: item.description,
          taskType: item.type,
          taskPoint: item.point,
          status: weekComplateSet.has(item._id)
            ? TaskStatus.Complete
            : TaskStatus
              .Pending,
        })
      }
      return item
    })

    // 3. 创建今日任务
    const isCreated = await db.collection('daily_task_records').where({
      childId,
      recordDate: getDate(),
    }).get()

    // 今日任务已经创建就不再创建
    if (isCreated.data.length > 0) {
      return ResponseUtil.success(isCreated.data[0].tasks)
    }

    const taskItem = {
      childId,
      childName: childrenRes.data.name,
      parentId: openId,
      recordDate: getDate(),
      tasks,
      completedPoints: 0,
      completedCount: 0,
      totalCount: tasks.length,
      createdAt: new Date(),
      updatedAt: new Date(),
    }

    await db.collection('daily_task_records').add(taskItem)

    return ResponseUtil.success(taskItem.tasks)
  }

  async list(data) {
    const { openId } = data

    let templates = await this.db.collection('task_templates').where({
      createdBy: openId,
    }).get()

    // 用户模版中的日任务
    const hasDailyTask = templates.data.some(item => item.type === TaskType.Day)
    // 用户模版中的周任务
    const hasWeeklyTask = templates.data.some(item => item.type === TaskType.Week)

    const systemTemplates = await this.db.collection('task_system_templates').get()
    const systemDailyTask = systemTemplates.data.filter(item => item.type === TaskType.Day)
    const systemWeeklyTask = systemTemplates.data.filter(item => item.type === TaskType.Week)

    // 如果没有配置，就用系统的
    if (!hasDailyTask) {
      templates.data.push(...systemDailyTask)
    }

    if (!hasWeeklyTask) {
      templates.data.push(...systemWeeklyTask)
    }

    return ResponseUtil.success(templates.data.map((item) => {
      return {
        id: item._id,
        title: item.title,
        description: item.description,
        type: item.type,
        point: item.point,
        isSystem: item.isSystem || false,
        children: item.children,
      }
    }))
  }

  async add(data) {
    const { openId, title, description, type, point, isSystem, id, children = [] } = data
    const db = this.db
    const dbCmd = db.command
    // 事务
    const transaction = await db.startTransaction()
    const records = transaction.collection('daily_task_records')
    const templates = transaction.collection('task_templates')

    const templatesData = await db.collection('task_templates').where({
      createdBy: openId,
    }).get()

    if (templatesData.data.length > 20) {
      return ResponseUtil.error('最多只能创建20个任务模板')
    }

    let templateId = id

    if (!templateId) {
      const template = await templates.add({
        createdBy: openId,
        title,
        description,
        type,
        point,
        children,
        isSystem: false,
      })
      templateId = template.id
    }
    else {
      const pushData = {
        createdBy: openId,
        title,
        description,
        type,
        point,
        children,
        isSystem: false,
      }

      if (isSystem) {
        type === TaskType.Day ? pushData.type = TaskType.Day : pushData.type = TaskType.Week
        const template = await templates.add({
          createdBy: openId,
          title,
          description,
          type,
          point,
          children,
          isSystem: false,
        })
        templateId = template.id
      }
      else {
        // 更新任务表
        await templates.doc(templateId).update({
          title,
          description,
          type,
          point,
          children,
          isSystem: false,
        })
      }
    }

    let oldChildren = []
    if (id) {
      const taskTemplate = await db.collection('task_templates').doc(id).get()
      oldChildren = taskTemplate.data[0].children
    }

    const needSubmitPromise = []

    // 删除的childId
    const deletedChildrenIds = oldChildren.filter(item => !children.includes(item))
    // 新增的childId
    const newChildrenIds = children.filter(item => !oldChildren.includes(item))
    // 编辑的childId
    const editedChildrenIds = children.filter(item => oldChildren.includes(item))

    // 存在新增
    if (newChildrenIds.length) {
      const newRecords = await db.collection('daily_task_records').where({
        childId: dbCmd.in(newChildrenIds),
        recordDate: getDate(),
      }).get()
      const result = newRecords.data.map(async (record) => {
        // 更新任务记录表
        const promise = records.doc(record._id).update({
          tasks: dbCmd.push({
            taskTitle: title,
            taskDescription: description,
            taskType: type,
            taskPoint: point,
            status: TaskStatus.Pending,
            taskId: templateId,
          }),
          totalCount: dbCmd.inc(1),
          updatedAt: new Date(),
        })
        needSubmitPromise.push(promise)
      })
    }

    // 存在编辑
    if (editedChildrenIds.length) {
      const newRecords = await db.collection('daily_task_records').where({
        childId: dbCmd.in(editedChildrenIds),
        recordDate: getDate(),
      }).get()
      const result = newRecords.data.map(async (record) => {
        const tasks = record.tasks.map((item) => {
          if (item.taskId === id) {
            return {
              ...item,
              taskTitle: title,
              taskDescription: description,
              taskType: type,
              taskPoint: point,
              status: TaskStatus.Pending,
              taskId: templateId,
            }
          }
          return item
        })
        // 更新任务记录表
        const promise = records.doc(record._id).update({
          tasks,
          updatedAt: new Date(),
        })
        needSubmitPromise.push(promise)
      })
    }

    // 存在删除
    if (deletedChildrenIds.length) {
      const newRecords = await db.collection('daily_task_records').where({
        childId: dbCmd.in(deletedChildrenIds),
        recordDate: getDate(),
      }).get()
      const result = newRecords.data.map(async (record) => {
        const tasks = record.tasks.filter(item => item.taskId !== id)
        console.log('tasks', tasks)
        // 更新任务记录表
        const promise = records.doc(record._id).update({
          tasks,
          totalCount: dbCmd.inc(-1),
          updatedAt: new Date(),
        })
        needSubmitPromise.push(promise)
      })
    }

    try {
      await Promise.all(needSubmitPromise)
      await transaction.commit()

      return ResponseUtil.success(null, '执行成功')
    }
    catch (err) {
      transaction.rollback()
      console.error('执行失败', err)
      return ResponseUtil.error('执行失败')
    }
  }

  async remove(data) {
    const { id } = data

    if (id) {
      await this.db.collection('task_templates').doc(id).remove()
    }

    return ResponseUtil.success(null, '删除成功')
  }

  async change(data) {
    const { id, childId } = data
    const db = this.db
    const dbCmd = db.command
    // 事务
    const transaction = await db.startTransaction()

    try {
      // 删除任务记录表中今日任务关联的任务
      const records = await db.collection('daily_task_records').where({
        childId,
        recordDate: getDate(),
      }).get()

      const submitPromise = []

      // 生成记录
      async function createTransaction(point, name, id, isComplete) {
        // 获取积分记录表
        const result = await db.collection('points_transaction').where({
          linked: id,
        }).get()
        if (!isComplete) {
          result.data.length && submitPromise.push(transaction.collection('points_transaction').doc(
            result.data[0]._id,
          )
            .remove())
        }
        else {
          submitPromise.push(transaction.collection('points_transaction').add({
            type: PointsAction.Exchange,
            childId,
            point,
            name,
            createAt: new Date(),
            linked: id,
          }))
        }

        submitPromise.push(transaction.collection('child').doc(childId).update({
          score: dbCmd.inc(isComplete ? point : -point),
        }))
      }

      const dailyTask = records.data[0]
      let currentTask = {}
      const tasks = dailyTask.tasks.map((item) => {
        if (item.taskId === id) {
          item.status = item.status === TaskStatus.Complete
            ? TaskStatus.Pending
            : TaskStatus
              .Complete
          currentTask = item
        }
        return item
      })

      await transaction.collection('daily_task_records').doc(dailyTask._id).update({
        updatedAt: new Date(),
        completedCount: dbCmd.inc(1),
        completedPoints: dbCmd.inc(currentTask.taskPoint),
        tasks,
      })

      console.log('currentTask', currentTask)
      if (Object.keys(currentTask).length) {
        await createTransaction(currentTask.taskPoint, currentTask.taskTitle, currentTask.taskId, currentTask.status === TaskStatus.Complete)
      }

      console.log('submitPromise', submitPromise)
      await Promise.all(submitPromise)
      await transaction.commit()

      return ResponseUtil.success(null, '更新成功')
    }
    catch (error) {
      console.error(error)
      transaction.rollback()
      return ResponseUtil.error('更新失败')
    }
  }

  async query(data) {
    const { childId, startDate, endDate } = data
    const db = this.db
    const dbCmd = db.command

    try {
      const list = await this.db.collection('daily_task_records').where({
        childId,
        recordDate: dbCmd.gte(startDate).and(dbCmd.lte(endDate)),
      }).get()

      return ResponseUtil.success(list.data.map((item) => {
        return {
          completedPoints: item.completedPoints,
          recordDate: item.recordDate,
          completedCount: item.completedCount,
          tasks: item.tasks,
        }
      }), '查询成功')
    }
    catch (err) {
      console.error(err)
      return ResponseUtil.error('查询失败')
    }
  }
}
